package com.siao.mvc
{
	import com.siao.data.ArrayList;
	import com.siao.data.HashMap;
	import com.siao.data.ValueObject;
	import com.siao.display.LayoutElement;
	import com.siao.events.ValueEvent;
	import com.siao.mvc.core.IContext;
	import com.siao.mvc.core.IMember;
	import com.siao.mvc.core.INotice;
	import com.siao.mvc.core.INotifier;
	import com.siao.mvc.managers.NoticeManager;
	import com.siao.mvc.notice.Notice;
	
	/**
	 * 视图
	 * @author SiaoLeon
	 */
	public class View extends LayoutElement implements IMember, INotifier
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		internal var _context:IContext;
		
		public function get context():IContext
		{
			return this._context;
		}
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		private var map:HashMap;
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 */
		public function View()
		{
			this.map = new HashMap();
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		public function onAdd():void
		{
		}
		
		public function onRemove():void
		{
		}
		
		public function notify(method:Object, params:*=null, queue:Object=null, isBlock:Boolean=false):INotice
		{
			return NoticeManager.instance.notify(new Notice(this, method, params, queue, isBlock));
		}
		
		/**
		 * 绑定数据
		 * @param source 原始数据
		 * @param target 目标数据
		 * @param map 属性映射对象，如：{sourceProperty:"targetPropertyName"}
		 */
		public function bind(source:ValueObject, target:Object, map:Object=null):void
		{
			if (!this.map.containsKey(source))
			{
				this.map.put(source, new HashMap());
				source.addEventListener(ValueEvent.CHANGE, onDataChange, false, 0, true);
			}
			
			var targets:HashMap = this.map.getValue(source) as HashMap;
			
			if (!targets.containsKey(target))
			{
				targets.put(target, new ArrayList());;
			}
			
			(targets.getValue(target) as ArrayList).add((map == null) ? target : map);
			
			this.mapObject(source);
		}
		
		/**
		 * 解除绑定
		 * @param source 原始数据
		 * @param target 目标数据
		 */
		public function unBind(source:ValueObject, target:Object):void
		{
			if (!this.map.containsKey(source))
			{
				return;
			}
			
			(this.map.getValue(source) as HashMap).remove(target);
			
			if ((this.map.getValue(source) as HashMap).size <= 0)
			{
				source.removeEventListener(ValueEvent.CHANGE, onDataChange);
				this.map.remove(source);
			}
		}
		
		/**
		 * 清除所有绑定
		 */
		public function clearBind():void
		{
			for each (var source:ValueObject in this.map.keys)
			{
				source.removeEventListener(ValueEvent.CHANGE, onDataChange);
				this.map.remove(source);
			}
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		/**
		 * 数据变更时
		 * @param event
		 */
		private function onDataChange(event:ValueEvent):void
		{
			var source:ValueObject = event.target as ValueObject;
			
			if (!this.map.containsKey(source))
			{
				return;
			}
			
			this.mapObject(source, event.name);
		}
		
		/**
		 * 映射源数据
		 * @param source
		 * @param property
		 */
		private function mapObject(source:ValueObject, property:String=null):void
		{
			//遍历与原始数据绑定的所有对象
			var targets:HashMap = this.map.getValue(source) as HashMap;
			
			for each (var target:Object in targets.keys)
			{
				//遍历该对象的所有映射关系
				var values:ArrayList = (targets.getValue(target) as ArrayList);
				
				for (var i:int = 0; i < values.length; i++)
				{
					var value:Object = values.element(i);
					
					if (target == value)
					{
						//如果未指定映射关系则直接赋值
						target = source;
					}
					else
					{
						//如果指定了映射关系则遍历寻找发生变更的属性并赋值
						for (var key:Object in value)
						{
							if (property == null || property == key)
							{
								var v:Object = value[key];
								
								if (target.hasOwnProperty(v))
								{
									target[v] = source[key];
								}
							}
						}
					}
				}
			}
		}
	
	}
}
